package com.xuelang.pipeline.app.pipeline.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xuelang.hiforce.base.tracing.TracingUtils;
import com.xuelang.hiforce.base.utils.message.Message;
import com.xuelang.jadp.client.sys.dto.UserInfoDTO;
import com.xuelang.pipeline.app.pipeline.PipelineInstanceService;
import com.xuelang.pipeline.app.pipeline.converter.PipelineInstanceToDTOConverter;
import com.xuelang.pipeline.app.resource.util.TektonUtil;
import com.xuelang.pipeline.app.task.TaskInstanceService;
import com.xuelang.pipeline.client.common.constant.Constant;
import com.xuelang.pipeline.client.common.exception.BizException;
import com.xuelang.pipeline.client.common.request.PageParam;
import com.xuelang.pipeline.client.common.result.ApiResult;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.client.pipeline.dto.PipelineInstanceConfigDTO;
import com.xuelang.pipeline.client.pipeline.dto.PipelineInstanceDTO;
import com.xuelang.pipeline.client.pipeline.dto.PipelineInstanceQuery;
import com.xuelang.pipeline.client.pipeline.dto.VariableSettingDTO;
import com.xuelang.pipeline.client.pipeline.enums.TaskResultTypeEnum;
import com.xuelang.pipeline.client.task.dto.TaskInstanceDTO;
import com.xuelang.pipeline.domain.pipeline.PipelineInstance;
import com.xuelang.pipeline.domain.pipeline.service.PipelineInstanceDomainService;
import com.xuelang.pipeline.domain.task.TaskInstance;
import com.xuelang.pipeline.domain.task.service.TaskInstanceDomainService;
import com.xuelang.sys.app.sys.UserManagerService;
import com.xuelang.sys.app.sys.utils.UserContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>流水线实例服务实现类</p>
 *
 * @author : yixin.lys
 * @date : 2024-06-24 18:17
 **/
@Slf4j
@Service
public class PipelineInstanceServiceImpl implements PipelineInstanceService {

    @Autowired
    private PipelineInstanceDomainService pipelineInstanceDomainService;

    @Autowired
    private TaskInstanceService taskInstanceService;

    @Autowired
    private TaskInstanceDomainService taskInstanceDomainService;

    @Autowired
    private UserManagerService userManagerService;

    @Override
    public PageRecord<PipelineInstanceDTO> page(PageParam<PipelineInstanceQuery> query) {
        Long currentPage = query.getCurrentPage();
        Long pageSize = query.getPageSize();
        PipelineInstanceQuery pipelineInstanceQuery = query.getCondition();
//        String pipelineCode = query.getCondition().getPipelineCode();
        PageRecord<PipelineInstance> pageResult = pipelineInstanceDomainService.pageByPipelineCode(currentPage, pageSize, pipelineInstanceQuery);

        List<PipelineInstanceDTO> record = pageResult.getRecords()
                .stream()
                .map(PipelineInstanceToDTOConverter.INSTANCE::toDTO)
                .collect(Collectors.toList());

        List<PipelineInstanceDTO> fullfilledCreator = record.stream().map(this::fullfillCreator).collect(Collectors.toList());
        return new PageRecord<>(
                pageResult.getCurrentPage(),
                pageResult.getPageSize(),
                pageResult.getTotalCount(),
                pageResult.getTotalPages(),
                fullfilledCreator
        );
    }

    private PipelineInstanceDTO fullfillCreator(PipelineInstanceDTO pipelineInstanceDTO) {
        String creatorId = pipelineInstanceDTO.getCreatorId();
        UserInfoDTO user = userManagerService.getUserById(creatorId);
        if (Objects.nonNull(user)) {
            pipelineInstanceDTO.setCreator(user.getRealName());
        } else {
            pipelineInstanceDTO.setCreator(Constant.UNKNOWN_USER);
        }
        return pipelineInstanceDTO;
    }

    @Override
    public List<PipelineInstanceDTO> listByPipelineCode(String pipelineCode) {
        PipelineInstanceQuery query = new PipelineInstanceQuery();
        query.setPipelineCode(pipelineCode);
        List<PipelineInstance> listResult = pipelineInstanceDomainService.listByQuery(query);
        if (CollectionUtils.isNotEmpty(listResult)) {
            return listResult.stream().map(PipelineInstanceToDTOConverter.INSTANCE::toDTO).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public List<PipelineInstanceDTO> listByComponentLabel(String componentLabel) {
        PipelineInstanceQuery query = new PipelineInstanceQuery();
        query.setComponentLabel(componentLabel);
        List<PipelineInstance> pipelineInstanceList = pipelineInstanceDomainService.listByQuery(query);
        if (CollectionUtils.isNotEmpty(pipelineInstanceList)) {
            return pipelineInstanceList.stream().map(PipelineInstanceToDTOConverter.INSTANCE::toDTO).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public void add(PipelineInstanceDTO pipelineInstance) {
        // TODO 根据逻辑补充一些默认值
        pipelineInstanceDomainService.add(PipelineInstanceToDTOConverter.INSTANCE.fromDTO(pipelineInstance));
    }

    @Override
    public void update(PipelineInstanceDTO pipelineInstance) {
        pipelineInstanceDomainService.update(PipelineInstanceToDTOConverter.INSTANCE.fromDTO(pipelineInstance));
    }

    @Override
    public void removeByIds(List<String> idList) {
        pipelineInstanceDomainService.removeByIds(idList);
    }

    @Override
    public void removeByCodes(List<String> codeList) {
        pipelineInstanceDomainService.removeByCodes(codeList);
    }

    @Override
    public PipelineInstanceConfigDTO getPipelineInstanceConfig(String pipelineCode) {
        PipelineInstanceQuery query = new PipelineInstanceQuery();
        query.setPipelineCode(pipelineCode);
        List<PipelineInstance> listResult = pipelineInstanceDomainService.listByQuery(query);
        if (listResult.isEmpty()) {
            throw new BizException("流水线实例不存在");
        }
        PipelineInstance pipelineInstance = listResult.get(0);
        List<TaskInstanceDTO> taskInstanceDTOS = taskInstanceService.queryByPipelineInstanceId(pipelineInstance.getInstanceCode());
        PipelineInstanceConfigDTO pipelineInstanceConfigDTO = new PipelineInstanceConfigDTO();
        pipelineInstanceConfigDTO.setPipelineInstanceDTO(PipelineInstanceToDTOConverter.INSTANCE.toDTO(pipelineInstance));
        pipelineInstanceConfigDTO.setTaskList(taskInstanceDTOS);
        //todo 全局变量。
        //pipelineInstanceConfigDTO.setVariableSettingList(pipelineInstance.getContextInfo());
        return pipelineInstanceConfigDTO;
    }

    @Override
    public PipelineInstanceConfigDTO getInstanceConfig(String flag, String code) {
        PipelineInstanceQuery query = new PipelineInstanceQuery();
        if ("1".equals(flag)) {
            query.setInstanceCode(code);
        } else {
            query.setPipelineCode(code);
        }
        List<PipelineInstance> listResult = pipelineInstanceDomainService.listByQuery(query);
        if (CollectionUtils.isEmpty(listResult)) {
            //没有执行实例的情况
            return new PipelineInstanceConfigDTO();
        }
        PipelineInstance pipelineInstance = listResult.get(0);
        List<TaskInstanceDTO> taskInstanceDTOS = taskInstanceService.queryByPipelineInstanceId(pipelineInstance.getInstanceCode());
        PipelineInstanceConfigDTO pipelineInstanceConfigDTO = new PipelineInstanceConfigDTO();
        PipelineInstanceDTO pipelineInstanceDTO = PipelineInstanceToDTOConverter.INSTANCE.toDTO(pipelineInstance);
        String creatorId = pipelineInstanceDTO.getCreatorId();
        UserInfoDTO user = userManagerService.getUserById(creatorId);
        if (Objects.nonNull(user)) {
            pipelineInstanceDTO.setCreator(user.getRealName());
        } else {
            pipelineInstanceDTO.setCreator(Constant.UNKNOWN_USER);
        }
        pipelineInstanceConfigDTO.setPipelineInstanceDTO(pipelineInstanceDTO);
        pipelineInstanceConfigDTO.setTaskList(taskInstanceDTOS);
        List<VariableSettingDTO> variableSettingList = JSON.parseArray(pipelineInstance.getContextInfo(), VariableSettingDTO.class);
        pipelineInstanceConfigDTO.setVariableSettingList(variableSettingList);
        return pipelineInstanceConfigDTO;
    }

    @Override
    public ApiResult<Boolean> instanceApprove(String type, String taskInstanceCode) {
        //先判断是否有权限。
        TaskInstance taskInstance = taskInstanceDomainService.queryByTaskCode(taskInstanceCode);
        String paramsJson = taskInstance.getParams();
        HashMap<String, String> taskParamMap = TektonUtil.parseTaskParamMap2O(paramsJson);
        String targetUserId = taskParamMap.get("verifier");
        String currentUserId = TracingUtils.getUserId();
        // 查看用户id是否匹配
        if (!targetUserId.contains(currentUserId)) {
            throw new BizException(Message.code("USER-NO-RIGHT-APPROVE-TASK", UserContextUtils.getUserAccount()).getDisplayText());
        }

        /**
         *  1。 根据type去调审批 通过 or 不通过 的实现类。   impl=> worker
         *  2. taskuuid  通过 or 不通过   建立一个 List<ResultInto>
         */
        //执行审批结果
        taskInstanceService.approveTaskInstance(taskInstanceCode, type);
        //更新审批状态
        List<TaskInstanceDTO.ResultInfo> resultTip = Lists.newArrayList();
        TaskInstanceDTO.ResultInfo updatedResult = new TaskInstanceDTO.ResultInfo();
        updatedResult.setType(TaskResultTypeEnum.checkPoint.getKey());
        List<Map<String, String>> dataList = Lists.newArrayList();
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("name", TracingUtils.getUserName());
        dataList.add(dataMap);
        updatedResult.setData(dataList);
        updatedResult.setPosition("right");
        resultTip.add(updatedResult);
        taskInstance.setResultTip(JSON.toJSONString(resultTip));
        taskInstanceDomainService.update(taskInstance);
        ApiResult<Boolean> result = ApiResult.success(true);
        result.setMessage("人工审批触发成功");
        return result;
    }
}
